package com.sh.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sh.common.BaseResult;
import com.sh.common.enums.BizCodeEnum;
import com.sh.common.enums.UsedEnum;
import com.sh.common.pojo.Contants;
import com.sh.common.pojo.bo.OperatorSaveBO;
import com.sh.common.pojo.bo.PutObjectRes;
import com.sh.common.pojo.query.OperatorPageQuery;
import com.sh.common.pojo.query.OperatorParseParam;
import com.sh.common.utils.FileUtil;
import com.sh.entity.FileResource;
import com.sh.entity.Operator;
import com.sh.entity.OperatorParam;
import com.sh.exceptions.BizException;
import com.sh.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.IOException;
import java.util.Date;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/operator")
public class OperatorController {

    @Autowired
    private IOperatorService operatorService;

    @Autowired
    private IOperatorParamService operatorParamService;

    @Autowired
    private IOSSService ossService;

    @Autowired
    private IFileResourceService fileResourceService;

    @PostMapping("/save")
    public BaseResult save(@Valid @RequestBody OperatorSaveBO saveBO) {
        FileResource fileResource = fileResourceService.getById(saveBO.getFileResourceId());
        if (fileResource == null) {
            return BaseResult.fail(BizCodeEnum.OPERATOR_RESOURCE_FILE_NOT_EXISTED);
        }
        Operator operator;
        if (saveBO.getId() != null) {
            operator = operatorService.getById(saveBO.getId());
            if (operator == null) {
                return BaseResult.success(BizCodeEnum.OPERATOR_NOT_EXISTED);
            }
        } else {
            QueryWrapper<Operator> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name", saveBO.getName()).or().eq("name_en", saveBO.getNameEn());
            if (operatorService.exists(queryWrapper)) {
                return BaseResult.fail(BizCodeEnum.OPERATOR_NAME_EXISTED);
            }
            operator = new Operator();
        }

        if (!saveBO.getFileResourceId().equals(operator.getFileResourceId())) {
            String operatorOssName = saveBO.getNameEn() + "_" + fileResource.getHashCode() + ".zip";
            String operatorOssKey = FileUtil.generateOperatorFileOssKey(saveBO.getNameEn(), operatorOssName);
            ossService.copyObject(fileResource.getFileUrl().substring(Contants.OSS_PREFIX.length()), operatorOssKey);
            operator.setOperatorUrl(Contants.OSS_PREFIX + operatorOssKey);
        }

        BeanUtil.copyProperties(saveBO, operator);
        operator.setUpdateTime(new Date());
        if (CollectionUtil.isNotEmpty(saveBO.getOperatorFiles())) {
            operator.setOperatorFileDetail(JSON.toJSONString(saveBO.getOperatorFiles()));
        }
        if (CollectionUtil.isNotEmpty(saveBO.getOperatorResults())) {
            operator.setResultInfo(JSON.toJSONString(saveBO.getOperatorResults()));
        }
        if (CollectionUtil.isNotEmpty(saveBO.getOperatorFuncParams())) {
            operator.setFuncParamInfo(JSON.toJSONString(saveBO.getOperatorFuncParams()));
        }
        List<OperatorParam> operatorParams = saveBO.getOperatorParams();
        if (CollectionUtil.isNotEmpty(operatorParams)) {
            operator.setParamInfo(JSON.toJSONString(operatorParams));
        }
        operatorService.saveOrUpdate(operator);
        return BaseResult.success(operator);
    }

    @PostMapping("/page")
    public BaseResult page(@Valid @RequestBody OperatorPageQuery query) {
        return BaseResult.success(operatorService.queryOperatorPage(query));
    }

    @PostMapping("/delete/{id}")
    public BaseResult delete(@PathVariable("id") Long id) {
        Operator operator = operatorService.getById(id);
        if (operator == null) {
            return BaseResult.fail(BizCodeEnum.DATA_NOT_EXISTED);
        }
        if (UsedEnum.USED.getCode().equals(operator.getUsed())){
            return BaseResult.fail(BizCodeEnum.OPERATOR_USED);
        }
        return BaseResult.success(operatorService.removeById(id));
    }

    @GetMapping("/{id}")
    public BaseResult getById(@PathVariable("id") Long id) {
        Operator operator = operatorService.getById(id);
        if (operator == null) {
            return BaseResult.fail(BizCodeEnum.DATA_NOT_EXISTED);
        }
        return BaseResult.success(operatorService.transferToDto(operator));
    }

    @PostMapping("/tree")
    public BaseResult getOperatorTree(@RequestBody OperatorPageQuery query) {
        return BaseResult.success(operatorService.queryOperatorTree(query));
    }


    @GetMapping("/check")
    public BaseResult check(@RequestParam("name") String name) {
        QueryWrapper<Operator> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name).or().eq("name_en", name);
        return BaseResult.success(!operatorService.exists(queryWrapper));
    }

}
